home *** CD-ROM | disk | FTP | other *** search
- TITLE MV - MSDOS FILE MOVE UTILITY
- PAGE 55,132
- ;***************************************************************************
- ; THIS PROGRAM RENAMES A FILE OR DIRECTORY, OR MOVES ONE OR MORE FILES
- ; OR DIRECTORIES BETWEEN DISKS OR DIRECTORIES.
- ;
- ; USAGE (afn = ambiguous file name, ufn = unambiguous file name,
- ; dir = directory):
- ;
- ; MV ufn1 ufn2 - renames or moves ufn1 to ufn2.
- ;
- ; MV afn1 afn2 ... dir - moves one or more files into dir.
- ;
- ; MV -R dir1 dir2 if dir2 doesn't exist, renames or moves
- ; dir1 to dir2.
- ; (note: DOS 2 requires that renaming a direc-
- ; tory be done by creating dir2, moving all
- ; files from dir1 into it, then deleting dir1).
- ;
- ; - if dir2 exists, makes dir1 a subdirectory
- ; of it.
- ;
- ; SWITCHES (OPTIONAL):
- ;
- ; I prompts before overwriting files
- ;
- ; R allows recursively moving directories.
- ;
- ; V turns on "verbose" mode (shows name of each file as it
- ; is moved).
- ;***************************************************************************
- ; TO BUILD MV.EXE:
- ; MASM MV,MV,NUL,NUL
- ; LINK MV,MV,NUL,ASM -C3100
- ;***************************************************************************
- ; BY: JON DART
- ; DEPARTMENT OF ANTHROPOLOGY
- ; UCSD C-001
- ; LA JOLLA, CA 92093
- ;***************************************************************************
- ; VERSION 2.1, 06-JUL-86 (CHANGES TO MEMORY ALLOC, ALLOWS HYPHEN FOR
- ; SWITCHES, NOW ASSEMBLES UNDER MASM 4.0)
- ; VERSION 2.0, 30-JUN-86 (MINOR CLEANING UP, R AND I SWITCHES ADDED, C
- ; SWITCH REMOVED)
- ; VERSION 1.9, 26-APR-86 (DOESN'T EXIT AFTER USER RESPONDS N TO
- ; OVERWRITE MSG.)
- ; VERSION 1.8, 31-MAR-86 (MORE BUG FIXES (*SIGH*))
- ; VERSION 1.7, 29-MAR-86 (BUG FIXES)
- ; VERSION 1.6, 24-MAR-86 (ALLOWS MULTIPLE SOURCE FILES)
- ; VERSION 1.5, 25-JAN-86 (ADDS CHECK FOR IDENTICAL SOURCE & DEST)
- ; VERSION 1.4, 14-JAN-86 (ADDS SWITCHES)
- ; VERSION 1.3, 12-JAN-86 (ADDS RECURSION)
- ; VERSION 1.2, 01-JAN-86
- ; VERSION 1.1, 01-NOV-85
- ; VERSION 1.0, 29-SEP-85
- ;***************************************************************************
-
- PATHSIZE EQU 65 ;MAX. SIZE OF DOS PATHNAME, +1
- BUFSIZE EQU 32*1024 ;SIZE OF COPY BUFFER
- MAXLEVEL EQU 12 ;MAX NESTING LEVEL FOR DIRECTORIES
- MAXARGS EQU 40 ;MAXIMUM # OF COMMAND LINE ARGUMENTS
- PRGSIZE EQU 1800H ;MAX. SIZE OF CODE AND FIXED DATA
- TRUE EQU 1
- FALSE EQU 0
- CONFIRM EQU FALSE ;"CONFIRM BEFORE OVERWRITE" OPTION (DEFAULT VALUE)
- RECURSE EQU FALSE ;"RECURSE" OPTION (DEFAULT VALUE)
- VERBOSE EQU FALSE ;"VERBOSE" OPTION (DEFAULT VALUE)
- M EQU BYTE PTR 0[BX]
- BIT$DIR EQU 00010000B ;BIT IN ATTRIBUTE FOR DIRECTORY
- BIT$RO EQU 00000001B ;BIT IN ATTRIBUTE FOR WRITE-PROTECT
-
- .XLIST
- INCLUDE ASCII.DEF
- INCLUDE MSDOS2.DEF
- INCLUDE MACROS.DEF
- .LIST
-
- MVINFO STRUC
- NEWDIR DW 1 DUP (?) ;FLAG, =1 IF NEW DIRECTORY CREATED
- SRCTYPE DB 2 DUP (?) ;TYPE OF SOURCE (0 IF UFN)
- DESTTYPE DB 2 DUP (?) ;TYPE OF DEST (0 IF UFN)
- ARG1 DB PATHSIZE DUP (?) ;FIRST ARGUMENT (SOURCE)
- ARG2 DB PATHSIZE DUP (?) ;SECOND ARGUMENT (DEST)
- ARG2A DB PATHSIZE DUP (?) ;SOURCE PREFIX + DEST
- SSPATH DB PATHSIZE DUP (?) ;SOURCE SEARCH PATH
- SPREFIX DB PATHSIZE DUP (?) ;SOURCE LEAD-IN PATH
- DSPATH DB PATHSIZE DUP (?) ;DEST SEARCH PATH
- ;(USED ONLY AS SCRATCH AREA)
- DPREFIX DB PATHSIZE DUP (?) ;DEST LEAD-IN PATH
- SRCNAME DB PATHSIZE DUP (?) ;UNAMBIGUOUS SOURCE NAME
- DESTNAME DB PATHSIZE DUP (?) ;UNAMBIG. DEST NAME
- DTA DB 128 DUP (?) ;DTA FOR SEARCH FN.
- MVINFO ENDS
- MVSTRUCSIZE EQU 9*PATHSIZE+135 ;SIZE OF STRUCTURE
-
- DGROUP GROUP DATA,STACK
- DATA SEGMENT WORD PUBLIC
- ; GLOBAL MEMORY DEFINITIONS:
- ;
- MSG1 DB 'MV Version 2.1 by Jon Dart (06-Jul-86)',CR,LF,CR,LF
- DB 'USAGE (afn = ambiguous file name, ufn = unambiguous file name,'
- DB CR,LF
- DB ' dir = directory):',CR,LF,CR,LF
- DB 'MV ufn1 ufn2 move or rename ufn1 to ufn2.',CR,LF,CR,LF
- DB 'MV afn1 afn2 ... dir move one or more files into dir.',CR,LF,CR,LF
- DB "MV -R dir1 dir2 if dir2 doesn't exist, move or rename"
- DB CR,LF
- DB ' dir1 to dir2.',CR,LF,CR,LF
- DB ' if dir2 exists, make dir1 a subdirectory'
- DB CR,LF
- DB ' of it.',CR,LF,CR,LF
- DB 'SWITCHES (OPTIONAL):',CR,LF,CR,LF
- DB '-I prompt before overwriting files.',CR,LF,CR,LF
- DB '-R allow recursive moving of directories.',CR,LF,CR,LF
- DB '-V echo file names as they are moved.',CR,LF
- DB 0
- MSG2 DB ': file not found.',CR,LF,0
- MSG3 DB 'Source and dest are incompatible.',CR,LF,0
- MSG4 DB ' exists. Overwrite [Y or N]? ',0
- MSG5 DB ': open failed.',CR,LF,0
- MSG6 DB ': file is R/O. Are you SURE [Y or N]? ',0
- MSG7 DB ': directory.',CR,LF,0
- MSG8 DB ': write error.',CR,LF,0
- MSG9 DB '; read error.',CR,LF,0
- MSG10 DB ': write error (probably disk full).',CR,LF,0
- MSG11 DB ': rename failed.',CR,LF,0
- MSG12 DB ": can't create.",CR,LF,0
- MSG13 DB ": can't remove.",CR,LF,0
- MSG14 DB "Directories nested too deep.",CR,LF,0
- MSG15 DB "Insufficient memory for buffers.",CR,LF,0
- MSG16 DB ": Illegal switch.",CR,LF,0
- MSG17 DB "Error: source and dest are identical.",CR,LF,0
- MSG18 DB "Too many arguments.",CR,LF,0
- DATA ENDS
-
- STACK SEGMENT PARA STACK
- DB 512 DUP (?)
- STACK ENDS
-
- ; VARIABLES AND BUFFER AREAS, STORED IN FREE MEMORY ABOVE PROGRAM,
- ; RELATIVE TO "BASE" (DS AND ES WILL NORMALLY POINT TO START OF THIS AREA):
-
- RBASE EQU 2 ;POINTER TO MVSTRUC IN RSTACK
- LEVEL EQU 4 ;RECURSION LEVEL
- SRCDRIVE EQU 6 ;SOURCE DRIVE (0 = DEFAULT)
- DESTDRIVE EQU 8 ;DEST DRIVE (0 = DEFAULT)
- INHANDLE EQU 10 ;INPUT FILE HANDLE
- OUTHANDLE EQU 12 ;OUTPUT FILE HANDLE
- IFLAG EQU 14 ;CONFIRM FLAG
- RFLAG EQU 16 ;RECURSE FLAG
- VFLAG EQU 18 ;VERBOSE FLAG
- CMDTAIL EQU 20 ;STORAGE FOR COMMAND TAIL
- DEST_DTA EQU CMDTAIL+128 ;HOLDS INFO ON DEST, RETURNED FROM DOS
- ;FN 4E.
- NUMARGS EQU DEST_DTA+128 ;NUMBER OF ARGUMENTS ON COMMAND LINE
- ARGPTRS EQU NUMARGS+2 ;POINTERS TO START OF ARGUMENTS
- BUFFER EQU ARGPTRS+(2*MAXARGS) ;FILE XFER BUFFER
- RSTACK EQU BUFFER+BUFSIZE ;RECURSION STACK
- DATASIZE EQU (RSTACK)+(MAXLEVEL*MVSTRUCSIZE)+256
-
- PAGE +
- CODE SEGMENT BYTE PUBLIC
- ASSUME CS:CODE,DS:DGROUP,ES:DGROUP,SS:STACK
- EXTRN CPYCNT:NEAR,UC:NEAR,UCSTR:NEAR,CRLF:NEAR,ERRORMSG:NEAR,COUT:NEAR
- EXTRN CIN:NEAR,CLRCO:NEAR,SKIPSP:NEAR,TYPTX:NEAR,ERRORMSG:NEAR,CLRCO:NEAR
- EXTRN FIXPATH:NEAR,GETYORN:NEAR,UNLINK2:NEAR
- EXTRN TYPE_DIR:ABS,TYPE_AFN:ABS,TYPE_UFN:ABS,TYPE_DSP:ABS,TYPE_DRV:ABS
- EXTRN TYPE_UNK:ABS
-
- ;*********************
- ;* MACRO DEFINITIONS *
- ;*********************
-
- ADDR MACRO REG,OFFST ;COMPUTE ADDRESS OFFSET FROM BASE REGISTER (BX)
- MOV REG,BX
- ADD REG,OFFSET OFFST
- ENDM
-
- ERROR MACRO ERRNUM ;SHOW ERROR MESSAGE
- MOV DX,OFFSET DGROUP:MSG&ERRNUM
- CALL PRTERR
- ENDM
-
- ;**********************
- ; PROGRAM ENTRY POINT *
- ;**********************
- ENTRY:
- TEST_DOS2 ;TEST FOR DOS 2.0, EXIT IF DOS 1
- MOV AX,DS
- MOV ES,AX
- MOV BX,((PRGSIZE+DATASIZE) SHR 4)+1 ;RESERVE SPACE FOR PROGRAM+BUFFERS
- MOV AH,SET_BLOCK
- INT DOS
- JB MEMERR ;IF ERROR
- MOV AX,DS ;GET DATA SEG
- ADD AX,PRGSIZE SHR 4 ;ADD OFFSET TO BUFFER AREA
- MOV ES,AX ;SET EXTRA SEG TO POINT TO BUFFERS
- JMP SHORT MEMOK
- MEMERR: ERROR 15
- JMP EXIT2
- MEMOK:
- MOV BX,OFFSET (80H) ;POINT TO BYTE COUNT FOR COMMAND LINE
- CMP [BX],BYTE PTR 0
- JE USEMSG ;IF NO COMMAND TAIL
- PUSH BX
- MOV DL,[BX]
- MOV DH,0
- ADD BX,DX
- INC BX
- MOV [BX],BYTE PTR 0 ;PUT 0 BYTE AT END OF COMMAND LINE
- POP BX
- INC BX
- CALL UCSTR ;CONVERT COMMAND LINE TO UPPER CASE
- CALL SKIPSP ;SKIP LEADING SPACES
- JNC L_2 ;IF SOMETHING ON LINE
- USEMSG: ERROR 1
- JMP EXIT2
- L_2:
- MOV SI,BX
- MOV DI,OFFSET CMDTAIL
- MOV CX,128
- CALL CPYCNT ;SAVE COMMAND TAIL
- MOV AX,ES
- MOV DS,AX ;SET DATA SEG TO VARIABLE AREA
- MOV BYTE PTR DS:IFLAG,CONFIRM ;SET CONFIRM FLAG DEFAULT
- MOV BYTE PTR DS:VFLAG,VERBOSE ;SET VERBOSE FLAG DEFAULT
- MOV BYTE PTR DS:RFLAG,FALSE ;SET RECURSIVE FLAG DEFAULT
- MOV WORD PTR DS:LEVEL,0 ;SET RECURSION LEVEL = 0
- MOV BYTE PTR DS:SRCDRIVE,0 ;SET SOURCE DRIVE DEFAULT
- MOV BYTE PTR DS:DESTDRIVE,0 ;SET DEST DRIVE DEFAULT
- ;***************************
- ; COLLECT SWITCHES, IF ANY *
- ;***************************
- MOV BX,OFFSET CMDTAIL ;POINT TO COMMAND TAIL
- NEXTSW:
- CALL SKIPSP
- JB USEMSG ;IF NOTHING ON LINE BESIDES SWITCHES
- CMP BYTE PTR [BX],'/' ;SWITCH SPECIFIED?
- JE GOTSW ;YES
- CMP BYTE PTR [BX],'-' ;CHECK FOR HYPHEN, TOO
- JNE NOSWITCH
- GOTSW:
- INC BX ;SKIP OVER SWITCH CHARACTER
- CALL SKIPSP ;SKIP LEADING BLANKS
- JB USEMSG ;IF NOTHING
- CALL UC ;MAKE SWITCH UPPER CASE
- CMP AL,'V' ;VERBOSE SWITCH?
- JE VSWITCH
- CMP AL,'I' ;INTERACTIVE SWITCH?
- JE ISWITCH
- CMP AL,'R' ;RECURSIVE SWITCH?
- JE RSWITCH
- CALL COUT ;DISPLAY BAD CHAR.
- ERROR 16 ;ILLEGAL SWITCH
- JMP EXIT2
- VSWITCH:
- MOV AL,1
- SUB AL,BYTE PTR DS:VFLAG
- MOV BYTE PTR DS:VFLAG,AL ;TOGGLE VFLAG
- INC BX ;SKIP SWITCH LETTER
- JMP NEXTSW
- ISWITCH:
- MOV AL,1
- SUB AL,BYTE PTR DS:IFLAG
- MOV BYTE PTR DS:IFLAG,AL ;TOGGLE IFLAG
- INC BX ;SKIP SWITCH LETTER
- JMP NEXTSW
- RSWITCH:
- MOV AL,1
- SUB AL,BYTE PTR DS:RFLAG
- MOV BYTE PTR DS:RFLAG,AL ;TOGGLE RFLAG
- INC BX ;SKIP SWITCH LETTER
- JMP NEXTSW
- ;************************************************************
- ; SCAN THE COMMAND LINE AND STORE POINTERS TO ALL ARGUMENTS *
- ;************************************************************
- NOSWITCH:
- MOV CX,0 ;CX COUNTS # OF ARGUMENTS
- MOV SI,OFFSET DS:ARGPTRS ;POINT TO ARG POINTER TABLE
- SAVEARG:
- INC CX ;BUMP ARGUMENT COUNT
- CMP CX,MAXARGS
- JG TOOMANY ;IF TOO MANY
- MOV DS:[SI],BX ;SAVE POINTER TO ARG
- ADD SI,2 ;ADVANCE TO NEXT TABLE ENTRY
- CNTARGS:
- MOV AL,DS:[BX] ;GET CHAR. FROM COMMAND LINE
- CMP AL,0
- JE ENDLINE ;IF END OF LINE
- COMPLIST <SPACE,TAB>,NEXTARG ;SEE IF SPACE OR TAB
- INC BX
- JMP CNTARGS ;LOOP TILL DELIMITER FOUND
- NEXTARG:
- CALL SKIPSP ;SKIP SPACES AND TABS
- JNB SAVEARG ;IF NOT EOL, BACK TO TOP OF LOOP
- ENDLINE:
- CMP CX,0 ;CHECK ARGUMENT COUNT
- JE NOARGS ;IF NO ARGS
- CMP CX,1
- JG ARGSOK ;IF >=2 ARGS
- MOV DS:[SI],BX ;EXACTLY ONE ARGUMENT, SO
- INC CX ;MAKE A DUMMY (NULL) 2ND ARGUMENT
- JMP SHORT ARGSOK
- NOARGS:
- JMP USEMSG ;ELSE USE MESSAGE
- TOOMANY:
- ERROR 18 ;TOO MANY ARGUMENTS (PRETTY UNLIKELY)
- JMP EXIT2
- ;************************************
- ;* COLLECT THE DESTINATION PATHNAME *
- ;************************************
- ARGSOK: MOV WORD PTR DS:NUMARGS,CX ;SAVE NUMBER OF ARGUMENTS
- DEC CX ;NUMBER OF ARGS - 1
- ADD CX,CX ;TIMES TWO
- MOV SI,OFFSET DS:ARGPTRS
- ADD SI,CX ;POINT TO ADDR. OF LAST ARGUMENT (DEST)
- MOV BX,DS:[SI] ;PUT ADDR. INTO BX
- MOV DI,OFFSET RSTACK+ARG2 ;POINT TO STORAGE FOR DEST
- MOV AL,[BX+1]
- CMP AL,':' ;CHECK FOR DEST DRIVE SPEC
- JNE GETLAST ;IF NONE
- MOV AL,[BX] ;DRIVE SPECIFIED, GET DRIVE LETTER
- SUB AL,'A'-1 ;MAKE BINARY
- MOV BYTE PTR DS:DESTDRIVE,AL ;SAVE DRIVE
- GETLAST: MOV AL,[BX] ;GET A CHAR. FROM CMD LINE
- COMPLIST <0,SPACE,TAB>,ENDARG2 ;IF DELIMITER
- STOSB ;NOT DELIMITER, STORE IT
- INC BX ;BUMP POINTER
- JMP GETLAST ;LOOP
- ENDARG2:
- MOV AL,0
- STOSB ;END DEST W. 0
- ;***********************************************************
- ;* LOOP, TAKING ONE SOURCE AT A TIME AND MOVING IT TO DEST *
- ;***********************************************************
- MOV CX,WORD PTR DS:NUMARGS ;GET NUMBER OF ARGS AGAIN
- DEC CX ;-1
- MOV SI,OFFSET DS:ARGPTRS ;POINT TO POINTER TABLE
- MOVE1ARG:
- MOV BX,DS:[SI] ;GET POINTER TO ARG
- PUSH SI
- PUSH CX
- CALL MOVEARG ;MOVE IT
- POP CX
- POP SI
- ADD SI,2 ;ADVANCE TO NEXT ARG POINTER
- LOOP MOVE1ARG ;LOOP TILL NO MORE ARGS TO MOVE
- JMP EXIT2
-
- ;**********************************
- ;* MOVE 1 SOURCE ARGUMENT TO DEST *
- ;**********************************
- MOVEARG PROC NEAR
- MOV BYTE PTR DS:SRCDRIVE,0 ;SET SOURCE DRIVE DEFAULT
- MOV DI,OFFSET RSTACK+ARG1 ;COLLECT SOURCE
- MOV AL,[BX+1]
- CMP AL,':' ;CHECK FOR SOURCE DRIVE SPEC
- JNE GETARG
- MOV AL,[BX] ;GET DRIVE LETTER
- SUB AL,'A'-1 ;MAKE BINARY
- MOV BYTE PTR DS:SRCDRIVE,AL ;SAVE SOURCE DRIVE
- GETARG: MOV AL,[BX] ;COPY FROM [BX] TO [DI] UNTIL DELIMITER
- COMPLIST <0,SPACE,TAB>,ENDARG
- STOSB
- INC BX
- JMP GETARG
- ENDARG: MOV AL,0
- STOSB ;END ARG1 W. ZERO
- MOV WORD PTR DS:RBASE,RSTACK ;SAVE OFFSET TO RSTACK
- CALL MOVEIT ;DO THE STUFF
- RET
- MOVEARG ENDP
-
- PAGE +
- ;********************************************************************
- ; THIS IS THE MOVE SUBROUTINE. IT ASSUMES THAT ARG1 AND ARG2 ARE
- ; SET UP PROPERLY IN THE RECURSION STACK AREA, AND THAT "RBASE" POINTS
- ; TO THE START OF THE DATA STRUCTURE FOR THIS RECURSION LEVEL.
- ;
- MOVEIT PROC NEAR
- MOV BX,WORD PTR DS:RBASE ;GET BASE ADDR. (POINTER TO MVINFO)
- CALL SETUP ;PARSE ARGUMENTS, CHECK FOR ERRORS
- JNC NOARGERR ;IF OK
- JMP EXIT2 ;QUIT IF ERROR
- ;******************************************
- ; SEE IF ANYTHING MATCHES THE SOURCE SPEC *
- ;******************************************
- NOARGERR:
- ADDR DX,SSPATH ;POINT TO SEARCH PATH
- MOV CX,31H ;SET SEARCH ATTRIBUTES
- MOV AH,FIND_FIRST
- INT DOS ;SEARCH FOR 1ST MATCH
- JNC SRCOK ;OK IF SOMETHING FOUND
- ADDR DX,ARG1
- CALL ERRORMSG ;ELSE SHOW ARGUMENT
- ERROR 2 ;SAY IT DOESN'T EXIST
- JMP EXIT2
- ;**************************************
- ; CREATE DEST DIRECTORY, IF NECESSARY *
- ;**************************************
- SRCOK: CMP WORD PTR [BX].NEWDIR,1 ;CHECK NEW DIRECTORY FLAG
- JNE GOTONE ;IF NOT SET
- ADDR DX,ARG2A ;POINT TO DEST NAME
- MOV AH,MKDIR
- INT DOS ;CREATE NEW DIRECTORY
- JNB GOTONE ;IF OK
- ADDR DX,ARG2A ;IF CAN'T CREATE,
- CALL ERRORMSG ;SHOW DIRECTORY NAME
- ERROR 12 ;AND ERROR MSG.
- JMP EXIT2 ;EXIT 2 DOS
- ;**************
- ; TOP OF LOOP *
- ;**************
- GOTONE:
- CALL BUILD_NAMES ;MAKE UNAMBIG. SOURCE AND DEST NAMES
- JNC NOSKIP
- JMP NEXTFILE ;IF SOURCE IS "." OR ".." OR = DEST
- NOSKIP:
- CMP BYTE PTR DS:VFLAG,TRUE ;CHECK VERBOSE FLAG
- JNE QUIET ;IF QUIET MODE
- ADDR DX,SRCNAME ;NOT QUIET, SHOW VERBIAGE
- CALL ERRORMSG
- CALL TYPTX
- DB ' -->',SPACE+200Q
- ADDR DX,DESTNAME
- CALL ERRORMSG
- CALL CRLF
- QUIET:
- TEST [BX].DTA+21,BIT$DIR ;IS SOURCE A DIRECTORY?
- JZ CHKDRIVES ;NO
- ;***********************************************
- ; IF SOURCE IS A DIRECTORY, RECURSIVELY MOVE IT*
- ;***********************************************
- CMP BYTE PTR DS:RFLAG,TRUE ;R FLAG SET?
- JNE NEXTFILE ;NO, SKIP OVER DIRECTORY
- CMP WORD PTR DS:LEVEL,MAXLEVEL-1 ;ARE WE AT MAX LEVEL?
- JL NOTMAX ;NO
- ERROR 14 ;YES, TOO DEEP
- JMP EXIT2
- NOTMAX:
- COPYPATH SRCNAME,(ARG1+MVSTRUCSIZE) ;COPY SOURCE DIRECTORY TO ARG1 AT NEXT LEVEL
- COPYPATH DESTNAME,(ARG2+MVSTRUCSIZE) ;COPY DEST NAME TO ARG2 AT NEXT LEVEL
- PUSH BX ;SAVE POINTER TO BASE
- INC WORD PTR DS:LEVEL ;INCREMENT RECURSION LEVEL
- ADD WORD PTR DS:RBASE,MVSTRUCSIZE ;ADVANCE BASE POINTER
- CALL MOVEIT ;MOVE THE DIRECTORY
- POP BX ;RESTORE BASE POINTER
- DEC WORD PTR DS:LEVEL ;DECREMENT RECURSION LEVEL
- SUB WORD PTR DS:RBASE,MVSTRUCSIZE ;RESTORE BASE TO PREVIOUS LEVEL
- ADDR DX,DTA
- MOV AH,SET_DTA
- INT DOS ;RESET DTA
- JMP SHORT NEXTFILE ;DO NEXT FILE
- ;*****************************************
- ; IF SOURCE IS A FILE, COPY OR RENAME IT *
- ;*****************************************
- CHKDRIVES:
- MOV AL,BYTE PTR DS:SRCDRIVE ;GET SOURCE DRIVE
- CMP AL,BYTE PTR DS:DESTDRIVE ;COMPARE W. DEST..
- JNE MOVEM
- CALL RENAME_FILE ;SAME DRIVE, JUST RENAME
- JMP SHORT NEXTFILE
- MOVEM: CALL COPY_FILE ;DIFFERENT DRIVE, COPY SOURCE TO DEST
- ;*****************
- ; BOTTOM OF LOOP *
- ;*****************
- NEXTFILE:
- MOV AH,FIND_NEXT
- INT DOS ;FIND NEXT MATCH, IF ANY
- JC NOMORE ;IF NONE
- JMP GOTONE ;GOT ONE, BACK TO TOP OF LOOP
- ;**********************
- ; NO MORE FILES, DONE *
- ; *********************
- NOMORE: MOV AX,WORD PTR [BX].SRCTYPE ;GET TYPE OF SOURCE
- CMP AX,TYPE_DIR ;DIRECTORY?
- JNE JUSTCLOSE ;NO
- ADDR DX,ARG1 ;YES, POINT TO NAME
- MOV AH,RMDIR
- INT DOS ;REMOVE IT
- JNB JUSTCLOSE
- ADDR DX,ARG1
- CALL ERRORMSG
- ERROR 13 ;COMPLAIN IF ERROR
- JMP CLOSE2
- ;**************
- ; NORMAL EXIT *
- ;**************
- JUSTCLOSE:
- MOV BX,WORD PTR DS:OUTHANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE OUTPUT FILE
- MOV BX,WORD PTR DS:INHANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE INPUT FILE
- RET ;ALL DONE
- MOVEIT ENDP
-
- PAGE +
- ;*************************************************************************
- ; THIS PROCEDURE PARSES ARG1 AND ARG2 AND CHECKS FOR INCOMPATIBLE TYPES
- ; (E.G. "MV FOOBAR *.*"). IF SUCCESSFUL, IT SETS SSPATH = SOURCE SEARCH
- ; PATH, SPREFIX = SOURCE PREFIX, DSPATH = DEST SEARCH PATH (NOT USED),
- ; DPREFIX = DEST PREFIX, SRCTYPE = SOURCE TYPE DESTTYPE = DESTINATION TYPE.
- ; IT ALSO SETS "NEWDIR"=1 IF THE DESTINATION DIRECTORY MUST BE CREATED.
- ; ALL OF THESE VARIABLES ARE IN A STRUCTURE OF TYPE 'MVINFO' IN THE RECURSION
- ; STACK AREA (STARTING AT THE ADDRESS IN 'RBASE').
- ;
- ; ON RETURN, THE CARRY FLAG IS SET IF AN ERROR OCCURRED.
- ;
- SETUP PROC NEAR
- MOV BX,WORD PTR DS:RBASE ;GET ADDR. OF DATA STRUCTURE
- MOV WORD PTR [BX].NEWDIR,0 ;CLEAR "NEW DIRECTORY" FLAG
- ADDR DX,DTA
- MOV AH,SET_DTA
- INT DOS ;SET DTA
- ADDR SI,ARG1
- ADDR DI,ARG2
- COMP_STRINGS ;COMPARE ARG1 AND ARG2
- JNE NOTIDENT ;IF NOT IDENTICAL
- ERROR 17 ;ARG1 = ARG2, BAD NEWS
- STC
- RET
- NOTIDENT:
- ADDR CX,SSPATH
- ADDR DX,SPREFIX
- PUSH BX
- ADD BX,OFFSET ARG1
- CALL FIXPATH ;PARSE SOURCE PATHNAME
- POP BX
- CMP AX,TYPE_UNK
- JNE GOODPATH ;IF APPARENTLY OK
- ADDR DX,ARG1
- CALL ERRORMSG
- ERROR 2 ;NONEXISTENT PATHNAME, COMPLAIN
- STC
- RET
- GOODPATH:
- MOV WORD PTR [BX].SRCTYPE,AX ;SAVE TYPE OF SOURCE
- CMP AX,TYPE_DIR ;IS IT A DIRECTORY?
- JNE RSET ;NO.
- CMP BYTE PTR DS:RFLAG,TRUE ;R FLAG SET?
- JE RSET ;IF OK
- ADDR DX,ARG1 ;SHOW NAME
- CALL ERRORMSG
- ERROR 7 ;COMPLAIN ABOUT DIRECTORY
- STC ;SIGNAL ERROR
- RET
- RSET:
- ADDR SI,ARG2
- PDEST: PUSH SI
- SRCBS: MOV AX,[SI] ;FIND END OF DEST
- COMPLIST <0,SPACE,TAB>,GOTEND
- INC SI
- JMP SRCBS
- GOTEND:
- DEC SI
- CMP [SI],BYTE PTR '\' ;DOES DEST SPEC END W. BACKSLASH?
- JNE NOBS ;NO, IT DOESN'T
- MOV [SI],BYTE PTR 0 ;IF SO, REMOVE IT
- NOBS: COPYPATH ARG2,ARG2A ;MAKE ARG2A = ARG2
- POP SI ;POINT TO START OF ARG2 AGAIN
- ADDR CX,DSPATH
- ADDR DX,DPREFIX
- PUSH BX
- MOV BX,SI
- CALL FIXPATH ;PARSE DEST PATHNAME
- POP BX
- MOV WORD PTR [BX].DESTTYPE,AX ;SAVE DEST TYPE
- CMP AL,TYPE_AFN
- JE BADDEST ;DEST CAN'T BE AFN
- CMP AL,TYPE_UFN
- JNE NOTUFN ;IF DEST TYPE IS UFN,
- CMP WORD PTR DS:NUMARGS,2 ;BETTER HAVE ONLY 1 SOURCE
- JG BADDEST
- CMP WORD PTR DS:SRCTYPE,TYPE_AFN ;AND SOURCE TYPE BETTER NOT BE AFN
- JNE NOTUFN
- BADDEST:
- ERROR 3
- STC
- RET
- NOTUFN:
- COMPLIST <TYPE_DSP,TYPE_DRV,TYPE_DIR>,DESTDSP ;IF DEST IS DIR OR DRIVE
- CMP AL,TYPE_UNK
- JNE SHORT DESTOK ;IF DEST EXISTS
- DESTNX:
- MOV AX,WORD PTR [BX].SRCTYPE ;DEST DOESN'T EXIST, SO IF
- CMP AL,TYPE_DIR ;SOURCE TYPE IS DIRECTORY,
- JNE DESTOK
- CALL SETUP_DEST_DIR ;MAKE DEST A DIRECTORY, TOO
- JMP SHORT DESTOK
- DESTDSP: MOV AX,WORD PTR [BX].SRCTYPE ;DEST IS DIRECTORY, DIR SPEC OR DRIVE
- CMP AL,TYPE_DIR ;IS SOURCE A DIRECTORY? -
- JNE DESTOK ;- NO
- CALL SETUP_SRC_DIR ;- YES, SOURCE IS DIRECTORY, SET IT UP
- JB ERRRET ;IF ERROR
- MOV AX,WORD PTR [BX].DESTTYPE
- CMP AX,TYPE_DIR ;IS DEST A DIRECTORY? -
- JNE DESTOK ;- NO
- CALL SETUP_DEST_DIR ;- YES, SET IT UP, TOO
- ;*******************************
- ; CHECK FOR INCOMPATIBLE TYPES *
- ;*******************************
- DESTOK:
- MOV CX,WORD PTR [BX].DESTTYPE ;GET DEST TYPE
- MOV AX,WORD PTR [BX].SRCTYPE ;GET SOURCE TYPE
- CMP AX,TYPE_DIR ;IS SOURCE A DIRECTORY? -
- JNE TYPEOK ;- NO, IT ISN'T
- CMP CX,TYPE_DIR ;- YES, SOURCE IS DIRECTORY,
- JE TYPEOK ;DEST BETTER BE DIRECTORY
- CMP CX,TYPE_DRV ;OR DRIVE SPEC
- JE TYPEOK
- ERROR 3 ;ELSE INCOMPATIBLE TYPE ERROR
- ERRRET: STC ;ERROR RETURN
- RET
- TYPEOK: CLC ;NORMAL RETURN
- RET
- SETUP ENDP
-
- ;**********************************************
- ; MOVE IS FROM DIR TO DIR, DIR SPEC OR DRIVE
- ; BUILD FULL DEST PATHNAME (IN ARG2A) AND CHECK
- ; ITS TYPE. (SETS CARRY ON ERROR)
- ;
- SETUP_SRC_DIR PROC NEAR
- COPYPATH ARG2,DSPATH ;COPY DEST DIRECTORY OR DRIVE SPEC TO
- ;DEST PATH (USE AS SCRATCH AREA)
- DEC DI ;BACK UP OVER NULL
- MOV AX,WORD PTR [BX].DESTTYPE
- CMP AX,TYPE_DIR ;SEE IF DEST IS DIRECTORY
- JNE NOTDIR ;NOPE
- MOV BYTE PTR [DI],'\' ;YES, ADD BACKSLASH TO DEST NAME
- INC DI
- DEC CX
- NOTDIR: ADDR SI,ARG1 ;POINT TO SOURCE DIRECTORY NAME
- CMP BYTE PTR [SI+1],':' ;DRIVE SPECIFIED? -
- JNE NODRV ;- NO IT WASN'T
- ADD SI,2 ;- YES, IT WAS, SKIP IT
- NODRV:
- CALL CPYCNT ;COPY SOURCE DIRECTORY NAME (MINUS
- ;DRIVE SPEC) TO DEST PATH
- COPYPATH DSPATH,ARG2A ;COPY AUGMENTED DEST PATH TO ARG2A
- ADDR CX,DSPATH
- ADDR DX,DPREFIX
- PUSH BX
- ADD BX,OFFSET ARG2A
- CALL FIXPATH ;PARSE FULL DEST PATHNAME
- POP BX
- MOV WORD PTR [BX].DESTTYPE,AX ;SAVE DEST TYPE
- CMP AL,TYPE_UNK
- JNE DESTXST ;IF DEST EXISTS
- MOV AX,WORD PTR [BX].SRCTYPE ;DEST DOESN'T EXIST, GET SOURCE TYPE
- CMP AX,TYPE_DIR ;IF SOURCE IS A DIRECTORY,
- JNE DESTXST
- MOV [BX].DESTTYPE,TYPE_DIR ;MAKE DEST A DIRECTORY, TOO
- DESTXST:
- CLC
- RET
- SETUP_SRC_DIR ENDP
-
- ;***************************************************************
- ; THIS PROCEDURE IS CALLED IF THE DESTINATION IS A NEW DIRECTORY
- ;
- SETUP_DEST_DIR PROC NEAR
- ADDR SI,DSPATH
- ADDR DI,DPREFIX
- PUSH DI
- MOV CX,PATHSIZE
- CALL CPYCNT ;COPY SEARCH PATH TO PREFIX
- POP DI
- MOV CX,PATHSIZE
- MOV AL,0
- REPNE SCASB ;FIND END OF DEST PREFIX
- DEC DI
- MOV [DI],BYTE PTR '\' ;ADD BACKSLASH
- MOV [DI+1],BYTE PTR 0
- MOV [BX].NEWDIR,WORD PTR 1 ;SET "NEW DIRECTORY FLAG"
- MOV WORD PTR [BX].DESTTYPE,TYPE_DIR ;SET DEST TYPE = DIRECTORY
- RET
- SETUP_DEST_DIR ENDP
-
- PAGE +
- ;****************************************************************************
- ; THIS ROUTINE TAKES THE INFO ON A FILE IN THE DTA AND USES IT TO GENERATE
- ; FULL, UNAMBIGUOUS SOURCE AND DESTINATION FILE NAMES BY ADDING THE NECESSARY
- ; DIRECTORY PREFIXES TO IT. IT SETS THE CARRY FLAG IF THE "FILE"
- ; IS "." OR "..", OR IF THE SOURCE IS IDENTICAL TO THE DESTINATION.
- ;
- BUILD_NAMES PROC NEAR
- COPYPATH SPREFIX,SRCNAME ;GET SOURCE PREFIX, COPY TO SOURCE NAME
- DEC DI ;BACK UP OVER NULL
- ADDR SI,(DTA+30) ;POINT TO FILE NAME WE FOUND
- CMP [SI],BYTE PTR '.' ;DOES IT START WITH .? -
- JNE NOTDOT ;- NO
- STC ;- YES, SET CARRY TO SKIP IT
- RET
- NOTDOT:
- CALL CPYCNT ;ADD IT TO SOURCE PREFIX
- CMP WORD PTR [BX].DESTTYPE,TYPE_UFN ;IS DEST A UFN?
- JE DESTUFN ;YES, JUST USE IT
- CMP WORD PTR [BX].DESTTYPE,TYPE_UNK
- JE DESTUFN ;DITTO IF DEST DOESN'T EXIST
- ;IF NOT, MAKE DEST NAME = SOURCE NAME
- COPYPATH DPREFIX,DESTNAME ;COPY DEST PREFIX TO DEST NAME
- DEC DI ;BACK UP OVER NULL
- ADDR SI,DTA+30 ;POINT TO FILE NAME WE FOUND
- CALL CPYCNT ;ADD IT TO DEST PREFIX
- JMP SHORT DONE ;GO TO NEXT STEP
- DESTUFN: ;DEST IS A FILE, NOT A DIRECTORY
- COPYPATH ARG2,DESTNAME ;SO DESTNAME JUST = ARG2
- DONE:
- CALL CHECK_NAMES ;CHECK SOURCE AND DEST FOR IDENTITY
- RET
- BUILD_NAMES ENDP
-
- PAGE +
- ;*********************************************************************
- ; THIS PROCEDURE CHECKS THE SOURCE AND DEST FILES, AND SETS THE CARRY
- ; FLAG IF THEY ARE IDENTICAL
- ;
- CHECK_NAMES PROC NEAR
- MOV BX,WORD PTR DS:RBASE ;GET ADDR. OF DATA STRUCTURE
- MOV AH,SET_DTA
- MOV DX,OFFSET DEST_DTA
- INT DOS ;SET DTA
- ADDR DX,ARG2 ;POINT TO DESTINATION
- MOV CX,0FFH
- MOV AH,FIND_FIRST
- INT DOS ;SEARCH FOR IT
- PUSHF
- ADDR DX,DTA
- MOV AH,SET_DTA
- INT DOS ;RESET DTA
- POPF
- JNB GOTDEST ;IF FOUND IT
- CLC ;OK IF IT DOESN'T EXIST
- RET
- GOTDEST: ADDR SI,DTA+21 ;POINT TO INFO ON SOURCE
- MOV DI,OFFSET DEST_DTA+21 ;POINT TO INFO ON DEST
- MOV CX,9 ;SIZE OF FILE ATTRIBUTES
- REPE CMPSB ;COMPARE SOURCE AND DEST
- JNE NOTEQU ;IF NOT =
- COMP_STRINGS ;COMPARE STRINGS
- JNE NOTEQU ;IF SOURCE AND DEST NAMES NOT EQUAL
- STC ;FILES ARE EQUAL (NAMES AND ATTRIB.)
- RET
- NOTEQU: CLC
- RET
- CHECK_NAMES ENDP
- PAGE +
- ;**************************************************************************
- ; THIS ROUTINE COPIES A SINGLE FILE (SRCNAME) TO ITS DESTINATION (DESTNAME)
- ; ON ANOTHER DISK.
- ;
- COPY_FILE PROC NEAR
- ADDR DX,SRCNAME ;DX = SOURCE FILE NAME
- MOV AL,READ_ACCESS
- MOV AH,DOS2_OPEN
- INT DOS ;TRY TO OPEN SOURCE FILE
- JC FAIL ;IF CAN'T
- MOV WORD PTR DS:INHANDLE,AX ;SAVE FILE HANDLE
- CALL GETOK ;GET CONFIRMATION IF DEST EXISTS
- JNC OKGIVEN ;IF OK TO DELETE
- MOV BX,WORD PTR DS:INHANDLE ;IF NOT OK, GET FILE HANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE INPUT FILE
- RET ;EXIT W/O MOVING
- FAIL: ADDR DX,SRCNAME ;POINT TO SOURCE FILE NAME
- CALL ERRORMSG ;SHOW IT
- ERROR 5 ;COMPLAIN THAT CAN'T OPEN
- JMP EXIT2 ;EXIT 2 DOS
- OKGIVEN: ADDR DX,DESTNAME
- MOV CL,BYTE PTR [BX].DTA+21 ;MAKE DEST ATTRIBUTES=SOURCE ATTRIB.
- MOV CH,0
- MOV AH,DOS2_CREATE
- INT DOS ;CREATE FILE (OR TRUNCATE OLD ONE)
- JNC CREATED ;IF OK
- ADDR DX,DESTNAME
- CALL ERRORMSG ;CREATE FAILED, SHOW FILE NAME
- ERROR 5 ;COMPLAIN THAT CAN'T OPEN
- JMP CLOSE1
- CREATED:
- MOV WORD PTR DS:OUTHANDLE,AX ;SAVE OUTPUT HANDLE
- COPYLOOP:
- PUSH BX
- MOV BX,WORD PTR DS:INHANDLE ;BX = FILE HANDLE
- MOV DX,OFFSET BUFFER ;DX = BUFFER OFFSET
- MOV CX,BUFSIZE ;CX = BUFFER SIZE
- MOV AH,READ ;USING DOS 2 CALL,
- INT DOS ;READ FROM SOURCE
- POP BX
- JC RDERR ;IF ERROR
- MOV CX,AX ;SAVE AMT. READ
- CMP AX,0
- JE ENDCOPY ;IF 0
- PUSH BX
- MOV BX,WORD PTR DS:OUTHANDLE ;BX = FILE HANDLE
- MOV DX,OFFSET BUFFER ;DX = BUFFER OFFSET
- MOV AH,WRITE
- INT DOS ;WRITE BUFFER TO DEST
- POP BX
- JC WRERR ;IF ERROR
- CMP AX,CX ;WERE ALL BYTES WRITTEN?
- JE COPYLOOP ;YES, KEEP GOING
- ADDR DX,DESTNAME ;POINT TO DEST NAME
- CALL ERRORMSG ;SHOW IT
- ERROR 10 ;PROBABLY DISK FULL
- JMP SCRATCH ;ABORT
- WRERR: ADDR DX,DESTNAME ;POINT TO DEST NAME
- CALL ERRORMSG ;SHOW IT
- ERROR 8 ;WRITE ERROR
- JMP SCRATCH ;ABORT
- RDERR: ADDR DX,SRCNAME ;POINT TO SOURCE NAME
- CALL ERRORMSG ;SHOW IT
- ERROR 9 ;READ ERROR
- JMP SCRATCH ;ABORT
- ENDCOPY: PUSH BX ;NO ERRORS
- MOV BX,WORD PTR DS:INHANDLE ;GET INPUT FILE HANDLE
- MOV AH,FILE_TIMES
- MOV AL,0 ;GET DATE AND TIME
- INT DOS ;GET IT
- MOV BX,WORD PTR DS:OUTHANDLE ;GET OUTPUT FILE HANDLE
- MOV AH,FILE_TIMES
- MOV AL,1
- INT DOS ;SET OUTPUT DATE AND TIME SAME AS INPUT
- MOV BX,WORD PTR DS:INHANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE INPUT FILE
- MOV BX,WORD PTR DS:OUTHANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE OUTPUT FILE
- POP BX
- ADDR DX,SRCNAME ;POINT TO SOURCE NAME
- CALL UNLINK2 ;REMOVE IT
- JB DELERR ;IF SOME PROBLEM
- RET ;ALL DONE
- DELERR: ADDR DX,SRCNAME ;CAN'T DELETE FILE, SHOW FILE NAME
- CALL ERRORMSG
- ERROR 13 ;AND ERROR MSG.
- RET
-
- SCRATCH:
- PUSH BX
- MOV BX,WORD PTR OUTHANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE OUTPUT FILE
- POP BX
- ADDR DX,DESTNAME
- CALL UNLINK2 ;REMOVE PARTIAL FILE
- JMP CLOSE1 ;CLOSE INPUT AND EXIT
-
- COPY_FILE ENDP
-
- PAGE +
- ;*******************************************************************
- ; THIS ROUTINE "MOVES" A FILE (SRCNAME) BY RENAMING IT (TO DESTNAME)
- ;
- RENAME_FILE PROC NEAR
- CALL GETOK ;SEE IF FILE EXISTS
- JNC OK ;USER SAID OK TO ERASE
- RET ;NOT OK, SKIP THIS ONE
- OK: ADDR DX,SRCNAME ;POINT TO SOURCE
- ADDR DI,DESTNAME ;AND DEST
- MOV AH,DOS2_RENAME
- PUSH BX
- INT DOS ;RENAME
- POP BX
- JNC RENOK ;IF OK
- ADDR DX,SRCNAME
- CALL ERRORMSG ;SHOW SOURCE
- ERROR 11 ;SHOULDN'T HAPPEN
- JMP EXIT2
- RENOK: RET
- RENAME_FILE ENDP
-
- PAGE +
- ;*******************************************************************
- ; THIS ROUTINE CHECKS TO SEE IF THE DEST FILE EXISTS.
- ; IF IT DOES, AND IF THE CONFIRM FLAG IS SET, IT ASKS
- ; FOR CONFIRMATION BEFORE DELETING THE FILE. IF THE
- ; CONFIRM FLAG IS NOT SET, IT JUST DELETES IT.
- ; ON EXIT, 'C'=1 IF THE USER REPLIED 'N' TO THE CONFIRM MSG.
- ;
- GETOK PROC NEAR
- ADDR DX,DESTNAME
- MOV AL,0
- MOV AH,CHMOD
- INT DOS ;GET ATTRIBUTES FOR DEST
- JNC EXISTS ;IF FILE EXISTS
- CLC
- RET
- EXISTS:
- CMP BYTE PTR DS:IFLAG,TRUE ;IS FLAG SET TO CONFIRM?
- JNE COK ;NO.
- ADDR DX,DESTNAME
- CALL ERRORMSG ;SHOW DEST FILE
- ERROR 4 ;ASK FOR CONFIRMATION
- CALL GETYORN ;GET Y OR N RESPONSE
- CMP AL,'Y' ;IS IT YES?
- JNE ABEXIT ;NO, SIGNAL CALLING ROUTINE
- COK:
- TRYAGAIN:
- ADDR DX,DESTNAME
- MOV AH,UNLINK
- INT DOS ;DELETE THE FILE
- JNC OKEXIT ;IF NO PROBLEM
- CMP AX,5 ;WAS FILE R/O? (THIS OUGHT TO BE
- ; THE ONLY POSSIBLE ERROR)
- JNE OKEXIT ;EXIT IF SOME OTHER ERROR
- ADDR DX,DESTNAME
- CALL ERRORMSG ;SHOW DEST FILE NAME
- ERROR 6 ;R/O FILE, QUERY USER AGAIN
- CALL GETYORN ;GET Y OR N RESPONSE
- CMP AL,'Y' ;TEST FOR 'Y' RESPONSE
- JNE ABEXIT ;ABORT IF USER SAYS 'N'
- MOV CX,0 ;'Y' TYPED CLEAR ALL ATTRIBUTES
- ADDR DX,DESTNAME ;POINT TO FILE NAME
- MOV AH,CHMOD
- MOV AL,1 ;CHANGE ATTRIBUTES
- INT DOS ;TRY MAKING IT R/W
- JMP TRYAGAIN ;TRY TO ERASE IT AGAIN
- ABEXIT: STC
- RET
- OKEXIT: CLC
- RET
- GETOK ENDP
-
- ; PRTERR = PRINT ERROR MESSAGE (DX POINTS TO OFFSET FROM DGROUP)
-
- PRTERR: PUSH DS
- MOV AX,DGROUP
- MOV DS,AX
- CALL ERRORMSG
- POP DS
- RET
-
- CLOSE2: MOV BX,WORD PTR OUTHANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE OUTPUT FILE
- CLOSE1:
- MOV BX,WORD PTR INHANDLE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE INPUT FILE
- EXIT2:
- MOV AH,EXIT
- INT DOS ;EXIT TO DOS
-
- CODE ENDS
- END ENTRY
-
-